/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package com.xy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xy.constants.ControlCharacter;
import com.xy.dto.PositionDTO;
import com.xy.entity.*;
import com.xy.service.*;
import com.xy.utils.CommonUtil;
import com.xy.vo.PositionVO;
import com.xy.excel.PositionExcel;
import com.xy.mapper.PositionMapper;
import com.xy.wrapper.PositionWrapper;
import com.xy.wrapper.ProjectWrapper;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 门禁点表 服务实现类
 *
 * @author BladeX
 * @since 2023-07-18
 */
@Service
@AllArgsConstructor
public class PositionServiceImpl extends BaseServiceImpl<PositionMapper, PositionEntity> implements IPositionService {

	private final IPositionGroupRelService positionGroupRelService;
	private final IPositionGroupService positionGroupService;
	private final IExhibitionPositionService exhibitionPositionService;
	private final IVenueService venueService;
	private final IGateService gateService;
	private final IPositionGateService positionGateService;


	@Override
	public IPage<PositionVO> selectPositionPage(IPage<PositionVO> page, PositionDTO position) {
		List<PositionVO> positionVOList = baseMapper.selectPositionPage(page, position);

		pointList(positionVOList);

		return page.setRecords(positionVOList);
	}

	@Override
	public PositionVO queryPosition(PositionEntity position) {
		//通过id查询门禁点
		PositionEntity positionEntity = baseMapper.selectById(position.getId());
		PositionVO positionVO = PositionWrapper.build().entityVO(positionEntity);
		LambdaQueryWrapper<PositionGroupRelEntity> wrapper = Wrappers.lambdaQuery();
		wrapper.eq(PositionGroupRelEntity::getPositionId,positionEntity.getId());
		//通过门禁点与门禁组关系表查询门禁组
		PositionGroupRelEntity positionGroupRelEntity= positionGroupRelService.getOne(wrapper);
		positionVO.setPositionGroupId(positionGroupRelEntity.getPositionGroupId());
		PositionGateEntity positionGate = positionGateService.getOne(Wrappers.<PositionGateEntity>query().lambda().eq(PositionGateEntity::getPositionId, positionEntity.getId()));
		if(Func.isNotEmpty(positionGate)){
			GateEntity gateEntity = gateService.getById(positionGate.getGateId());
			positionVO.setGateName(gateEntity.getGateName());
		}
		return positionVO;
	}

	@Override
	public List<PositionEntity> listNotPage(PositionDTO position) {
		return dataList(position);
	}

	@Override
	public List<PositionEntity> listNotQuery(PositionDTO position) {
		if (position.getPositionGroupId() != null) {
			return dataList(position);
		}
		return this.list(Condition.getQueryWrapper(position));
	}

	@Override
	public List<PositionVO> listNotExhibition(PositionDTO position) {
		List<PositionEntity> list = this.list(Condition.getQueryWrapper(position));
		LambdaQueryWrapper<ExhibitionPositionEntity> wrapper = Wrappers.lambdaQuery();
		wrapper.eq(ExhibitionPositionEntity::getExhibitionId, position.getExhibitionId());
		List<ExhibitionPositionEntity> entityList = exhibitionPositionService.list(wrapper);
		Map<Long, List<ExhibitionPositionEntity>> collect = entityList.stream().collect(Collectors.groupingBy(ExhibitionPositionEntity::getPositionId));
		List<PositionEntity> collect1 = list.stream().filter(o -> !collect.containsKey(o.getId())).collect(Collectors.toList());
		List<PositionVO> positionVOList = BeanUtil.copy(collect1,PositionVO.class);
		pointList(positionVOList);
		if (position.getPositionGroupId() != null) {
			List<PositionVO> voList = positionVOList.stream().filter(s -> s.getPositionGroupId().equals(position.getPositionGroupId())).collect(Collectors.toList());
			return voList;
		}
		return positionVOList;
	}


	public List<PositionEntity> dataList(PositionDTO position) {
		LambdaQueryWrapper<PositionGroupRelEntity> wrapper = Wrappers.lambdaQuery();
		wrapper.eq(PositionGroupRelEntity::getPositionGroupId, position.getPositionGroupId());
		List<PositionGroupRelEntity> entityList = positionGroupRelService.list(wrapper);
		List<PositionEntity> list = new ArrayList<>();
		entityList.forEach(o -> {
			PositionEntity entity = this.getById(o.getPositionId());
			list.add(entity);
		});
		return list;
	}
	@Override
	public List<PositionExcel> exportPosition(Wrapper<PositionEntity> queryWrapper) {
		List<PositionExcel> positionList = baseMapper.exportPosition(queryWrapper);
		//positionList.forEach(position -> {
		//	position.setTypeName(DictCache.getValue(DictEnum.YES_NO, Position.getType()));
		//});
		return positionList;
	}

	@Override
	public Boolean savePosition(PositionDTO position) {
		PositionGroupRelEntity positionGroupRel = new PositionGroupRelEntity();
		positionGroupRel.setPositionId(position.getId());
		positionGroupRel.setPositionGroupId(position.getPositionGroupId());
		return positionGroupRelService.save(positionGroupRel);
	}

	@Override
	public Boolean saveOrUpdatePosition(PositionDTO position) {
		if(Func.isEmpty(position.getId())){
			position.setPositionCode(CommonUtil.deviceNo());
		}

		this.saveOrUpdate(position);

		PositionGroupRelEntity positionGroupRel = new PositionGroupRelEntity();
		positionGroupRel.setPositionId(position.getId());
		PositionGroupRelEntity groupRel = positionGroupRelService.getOne(Condition.getQueryWrapper(positionGroupRel));
		if (groupRel != null) {
			BeanUtil.copy(groupRel, positionGroupRel);
		}
		positionGroupRel.setPositionGroupId(position.getPositionGroupId());

		return positionGroupRelService.saveOrUpdate(positionGroupRel);
	}

	public void pointList(List<PositionVO> pointVOList) {
		List<PositionGroupRelEntity> relEntityList = positionGroupRelService.list();
		Map<Long, PositionGroupRelEntity> relEntityMap = relEntityList.stream().collect(Collectors.toMap(PositionGroupRelEntity::getPositionId, o -> o));
		List<PositionGroupEntity> positionGroupEntityList = positionGroupService.list();
		Map<Long, PositionGroupEntity> pointGroupEntityMap = positionGroupEntityList.stream().collect(Collectors.toMap(PositionGroupEntity::getId, o -> o));
		List<VenueEntity> venueEntities = venueService.list();
		Map<Long, VenueEntity> venueEntityMap = venueEntities.stream().collect(Collectors.toMap(VenueEntity::getId, o -> o));
		pointVOList.forEach(o -> {
			PositionGroupRelEntity positionGroupRel = relEntityMap.get(o.getId());
			PositionGroupEntity positionGroup = pointGroupEntityMap.get(positionGroupRel.getPositionGroupId());
			o.setGroupName(positionGroup!=null?positionGroup.getGroupName(): ControlCharacter.DELETED);
			o.setPositionGroupId(positionGroupRel.getPositionGroupId());
			if (o.getVenueId() != null) {
				VenueEntity venue = venueEntityMap.get(o.getVenueId());
				o.setVenueName(venue.getVenueAs());
			}

			PositionGateEntity positionGate = positionGateService.getOne(Wrappers.<PositionGateEntity>query().lambda().eq(PositionGateEntity::getPositionId, o.getId()));
			if(Func.isNotEmpty(positionGate)){
				GateEntity gateEntity = gateService.getById(positionGate.getGateId());
				o.setGateName(gateEntity.getGateName());
			}
		});
	}

}
